﻿using System;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Workflow.ComponentModel;
using System.Collections.Generic;

namespace Argos.Activities.MessageDelivery
{
	[DisplayName("File Delivery Activity")]
	[Description("A message delivery activity that stores the message in a file. The address is the full path to the file to store the message in.")]
	public class FileDeliveryActivity : MessageDeliveryActivityBase
	{

		#region public int MaxFileCount { get; set; }

		public static readonly DependencyProperty MaxFileCountProperty = DependencyProperty.Register("MaxFileCount", typeof(int), typeof(FileDeliveryActivity));

		[Category("Data")]
		[Description("Specifies the maximum number of files that are allowed in the directory where this alert delivery activity stores the alerts. When there are more files than this property specifies, the oldest files are deleted. Setting this value to 0 means that there is no upper limit for the number of files.")]
		public int MaxFileCount
		{
			get { return (int)this.GetValue(MaxFileCountProperty); }
			set { if (value < 0) { throw new ArgumentOutOfRangeException("MaxFileCount", "The value cannot be less than 0."); } this.SetValue(MaxFileCountProperty, value); }
		}

		#endregion
		
		
		protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
		{

			this.WriteFile();

			if (this.MaxFileCount > 0)
			{
				string path = this.GetFullFilePath(".txt");
				DirectoryInfo di = new FileInfo(path).Directory;
				int fileCount = di.GetFiles().Length;
				if (fileCount > this.MaxFileCount)
				{
					List<string> deleteList = new List<string>(Directory.GetFiles(di.FullName).Take(fileCount - this.MaxFileCount));

					Action<string> deleteHandler = delegate(string s)
					{
						try
						{
							File.Delete(s);
						}
						catch { }
					};

					deleteList.ForEach(deleteHandler);
				}
			}

			return ActivityExecutionStatus.Closed;
		}

		#region protected string GetFullFilePath(string defaultExtension)

		/// <summary>
		/// Returns the full path to the file to write in the activity.
		/// </summary>
		/// <param name="defaultExtension">The default extension to use for the file.</param>
		protected string GetFullFilePath(string defaultExtension)
		{
			if (string.IsNullOrEmpty(defaultExtension))
				throw new ArgumentNullException("defaultExtension");

			string path = this.Message.RecipientAddress;

			if (Directory.Exists(path))
			{
				if (!defaultExtension.StartsWith("."))
					defaultExtension = "." + defaultExtension;

				// If the given address is a folder, then create a unique file name for the alert.
				path = string.Format(@"{0}\{1:yyyyMMddHHmmssfffff}_{3}_{4}{2}", path, DateTime.UtcNow, defaultExtension, this.Message.AlertType, this.Message.Target.Id);
			}

			return path;
		}

		#endregion

		#region protected virtual void WriteFile()

		/// <summary>
		/// This method takes care of doing the actual writing of the file.
		/// </summary>
		protected virtual void WriteFile()
		{
			string path = this.GetFullFilePath(".txt");

			// Open the file in append mode, which either creates a new file or appends the
			// text to an existing file.
			using (FileStream strm = new FileStream(path, FileMode.Append, FileAccess.Write))
			{
				using (StreamWriter writer = new StreamWriter(strm))
				{
					writer.Write(this.Message.Body);
				}
			}
		}

		#endregion

	}
}
